package com.example.ovulationperiodtracker.view;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.drawable.Drawable;
import android.text.TextUtils;

import androidx.core.content.ContextCompat;

import com.example.ovulationperiodtracker.R;
import com.example.ovulationperiodtracker.model.Note;
import com.example.ovulationperiodtracker.utils.CalendarUtils;
import com.example.ovulationperiodtracker.utils.JCGSQLiteHelper;
import com.example.ovulationperiodtracker.utils.MyLog;
import com.necer.calendar.ICalendar;
import com.necer.painter.CalendarPainter;
import com.necer.utils.NAttrs;


import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class MyInnerPainter implements CalendarPainter {

    private final Context mContext;
    private final ICalendar iCalendar;
    private final Paint mTextPaint;
    private final int noAlphaColor = 255;
    private final List<LocalDate> mWorkdayList;
    private final List<LocalDate> mPointList;
    private final Map<LocalDate, String> mReplaceLunarStrMap;
    private final Map<LocalDate, Integer> mReplaceLunarColorMap;
    private final Map<LocalDate, String> mStretchStrMap;
    private final Drawable mDefaultCheckedBackground;
    private final Drawable mTodayCheckedBackground;
    private final Drawable mDefaultCheckedPoint;
    private final Drawable mDefaultUnCheckedPoint;
    private final Drawable mTodayCheckedPoint;
    private final Drawable mTodayUnCheckedPoint;
    private final DateTimeFormatter mDateFormatter;


    DateTimeFormatter formatter;
    public static List<LocalDate> paiLuanRi;
    public static List<LocalDate> yiYunQi;
    public static List<LocalDate> jingData;
    public static List<LocalDate> jingShiJiData;
    public static List<LocalDate> yuChanData;

    public MyInnerPainter(Context mContext, ICalendar iCalendar) {
        this.mContext = mContext;
        this.iCalendar = iCalendar;

        initJingData();

        mTextPaint = new Paint();
        mTextPaint.setAntiAlias(true);
        mTextPaint.setTextAlign(Paint.Align.CENTER);

        mPointList = new ArrayList<>();
        mWorkdayList = new ArrayList<>();
        mReplaceLunarStrMap = new HashMap<>();
        mReplaceLunarColorMap = new HashMap<>();
        mStretchStrMap = new HashMap<>();

        mDefaultCheckedBackground = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getDefaultCheckedBackground());
        mTodayCheckedBackground = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getTodayCheckedBackground());
        mDefaultCheckedPoint = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getDefaultCheckedPoint());
        mDefaultUnCheckedPoint = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getDefaultUnCheckedPoint());
        mTodayCheckedPoint = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getTodayCheckedPoint());
        mTodayUnCheckedPoint = ContextCompat.getDrawable(mContext, NAttrs.INSTANCE.getTodayUnCheckedPoint());

        mDateFormatter = DateTimeFormatter.ofPattern("yyyy-M-d");

        formatter = DateTimeFormatter.ofPattern("yyyyMMdd");

    }

    @Override
    public void onDrawToday(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) {

        if (yuChanData.contains(localDate)) {
            drawYuchan(localDate, canvas, rectF);
        } else {
            drawYiYunQi(localDate, canvas, rectF);
            drawJing(localDate, canvas, rectF);
            drawPaiLuan(localDate, canvas, rectF);
            drawShiJiJing(localDate, canvas, rectF);
        }


        mTextPaint.setTextSize(NAttrs.INSTANCE.getHolidayWorkdayTextSize());
        mTextPaint.setColor(Color.parseColor("#FF557C"));

        int[] holidayLocation = getToadyLocation(rectF.centerX(), rectF.centerY());
        canvas.drawText("今", (float) holidayLocation[0],
                getTextBaseLineY((float) holidayLocation[1]), mTextPaint);

        if (checkedDateList.contains(localDate)) {
            drawCheckedBackground(canvas, mTodayCheckedBackground, rectF, noAlphaColor);
            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getTodayCheckedSolarTextColor(), noAlphaColor);
            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getTodayCheckedLunarTextColor(), noAlphaColor);
            drawPoint(canvas, rectF, localDate, mTodayCheckedPoint, noAlphaColor);
            ;
        } else {
            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getTodayUnCheckedSolarTextColor(), noAlphaColor);
            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getTodayUnCheckedLunarTextColor(), noAlphaColor);
            drawPoint(canvas, rectF, localDate, mTodayUnCheckedPoint, noAlphaColor);
        }

        drawSex(localDate, canvas, rectF);
    }

    @Override
    public void onDrawCurrentMonthOrWeek(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) {
        if (yuChanData.contains(localDate)) {
            drawYuchan(localDate, canvas, rectF);
        } else {
            drawYiYunQi(localDate, canvas, rectF);
            drawJing(localDate, canvas, rectF);
            drawPaiLuan(localDate, canvas, rectF);
            drawShiJiJing(localDate, canvas, rectF);
        }
        if (checkedDateList.contains(localDate)) {
            drawCheckedBackground(canvas, mDefaultCheckedBackground, rectF, noAlphaColor);
            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultCheckedSolarTextColor(), noAlphaColor);
            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultCheckedLunarTextColor(), noAlphaColor);
            drawPoint(canvas, rectF, localDate, mDefaultCheckedPoint, noAlphaColor);

        } else {
            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedSolarTextColor(), noAlphaColor);
            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedLunarTextColor(), noAlphaColor);
            drawPoint(canvas, rectF, localDate, mDefaultUnCheckedPoint, noAlphaColor);

        }

        drawSex(localDate, canvas, rectF);

    }

    @Override
    public void onDrawLastOrNextMonth(Canvas canvas, RectF rectF, LocalDate localDate, List<LocalDate> checkedDateList) {
//        if (checkedDateList.contains(localDate)) {
//            drawCheckedBackground(canvas, mDefaultCheckedBackground, rectF, NAttrs.INSTANCE.getLastNextMothAlphaColor());
//            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultCheckedSolarTextColor(), NAttrs.INSTANCE.getLastNextMothAlphaColor());
//            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultCheckedLunarTextColor(), NAttrs.INSTANCE.getLastNextMothAlphaColor());
//            drawPoint(canvas, rectF, localDate, mDefaultCheckedPoint, NAttrs.INSTANCE.getLastNextMothAlphaColor());
//        } else {
//            drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedSolarTextColor(), NAttrs.INSTANCE.getLastNextMothAlphaColor());
//            drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedLunarTextColor(), NAttrs.INSTANCE.getLastNextMothAlphaColor());
//            drawPoint(canvas, rectF, localDate, mDefaultUnCheckedPoint, NAttrs.INSTANCE.getLastNextMothAlphaColor());
//        }


    }

    @Override
    public void onDrawDisableDate(Canvas canvas, RectF rectF, LocalDate localDate) {
        drawSolar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedSolarTextColor(), NAttrs.INSTANCE.getDisabledAlphaColor());
        drawLunar(canvas, rectF, localDate, NAttrs.INSTANCE.getDefaultUnCheckedLunarTextColor(), NAttrs.INSTANCE.getDisabledAlphaColor());
        drawPoint(canvas, rectF, localDate, mDefaultUnCheckedPoint, NAttrs.INSTANCE.getDisabledAlphaColor());
    }

    // 选中背景
    private void drawCheckedBackground(Canvas canvas, Drawable drawable, RectF rectF, int alphaColor) {
        Rect drawableBounds = getDrawableBounds((int) rectF.centerX(), (int) rectF.centerY(), drawable);
        drawable.setBounds(drawableBounds);
        drawable.setAlpha(alphaColor);
        drawable.draw(canvas);
    }

    // 绘制公历
    private void drawSolar(Canvas canvas, RectF rectF, LocalDate date, int color, int alphaColor) {
        mTextPaint.setColor(color);
        mTextPaint.setAlpha(alphaColor);
        mTextPaint.setTextSize(NAttrs.INSTANCE.getSolarTextSize());
        // mTextPaint.setFakeBoldText(NAttrs.INSTANCE.getSolarTextBold);

        float y = getTextBaseLineY(rectF.centerY());
        canvas.drawText(String.valueOf(date.getDayOfMonth()), rectF.centerX(), y, mTextPaint);
    }

    // 绘制农历
    private void drawLunar(Canvas canvas, RectF rectF, LocalDate localDate, int color, int alphaColor) {
//        if (NAttrs.INSTANCE.showLunar) {
//            ChineseDate chineseDate = new ChineseDate(localDate);
//            String lunarString;
//
//            // 农历部分文字展示优先顺序
//            String replaceString = mReplaceLunarStrMap.get(localDate);
//            if (!TextUtils.isEmpty(replaceString)) {
//                lunarString = replaceString;
//            } else if (!TextUtils.isEmpty(chineseDate.getLunarFestivals())) {
//                lunarString = chineseDate.getLunarFestivals();
//            } else if (!TextUtils.isEmpty(chineseDate.getTerm())) {
//                lunarString = chineseDate.getTerm();
//            } else if (!TextUtils.isEmpty(chineseDate.getSolarFestivals())) {
//                lunarString = chineseDate.getSolarFestivals();
//            } else {
//                String chineseText = chineseDate.getChineseDay();
//                if (chineseText.equals("初一")) {
//                    chineseText = chineseDate.getChineseMonthName();
//                }
//                lunarString = chineseText;
//            }
//
//            Integer replaceColor = mReplaceLunarColorMap.get(localDate);
//            mTextPaint.setColor(replaceColor != null ? replaceColor : color);
//            mTextPaint.setTextSize(NAttrs.INSTANCE.lunarTextSize);
//            mTextPaint.setAlpha(alphaColor);
//            mTextPaint.setFakeBoldText(NAttrs.INSTANCE.lunarTextBold);
//
//            canvas.drawText(lunarString, rectF.centerX(), rectF.centerY() + NAttrs.INSTANCE.lunarDistance, mTextPaint);
//        }

        NoteUtils.DayNote dayNote = NoteUtils.getDayNote(localDate);
        mTextPaint.setTextSize(NAttrs.INSTANCE.getLunarTextSize());
        mTextPaint.setColor(Color.parseColor("#ED6465"));
        if (dayNote.jingStart == 1) {
            canvas.drawText("经期开始", rectF.centerX(), rectF.centerY() + NAttrs.INSTANCE.getLunarDistance(), mTextPaint);
        }
        if (dayNote.jingEnd == 1) {
            canvas.drawText("经期结束", rectF.centerX(), rectF.centerY() + NAttrs.INSTANCE.getLunarDistance(), mTextPaint);
        }

    }

    // 绘制标记
    private void drawPoint(Canvas canvas, RectF rectF, LocalDate date, Drawable drawable, int alphaColor) {
        if (mPointList.contains(date)) {
            float centerY = (NAttrs.INSTANCE.getPointLocation() == NAttrs.INSTANCE.DOWN)
                    ? rectF.centerY() + NAttrs.INSTANCE.getPointDistance()
                    : rectF.centerY() - NAttrs.INSTANCE.getPointDistance();

            Rect drawableBounds = getDrawableBounds((int) rectF.centerX(), (int) centerY, drawable);
            drawable.setBounds(drawableBounds);
            drawable.setAlpha(alphaColor);
            drawable.draw(canvas);
        }
    }


    // canvas.drawText的基准线
    private float getTextBaseLineY(float centerY) {
        Paint.FontMetrics fontMetrics = mTextPaint.getFontMetrics();
        return centerY - (fontMetrics.bottom - fontMetrics.top) / 2 - fontMetrics.top;
    }


    // 设置标记
    public void setPointList(List<String> list) {
        mPointList.clear();
        for (String s : list) {
            LocalDate localDate;
            try {
                localDate = LocalDate.parse(s, mDateFormatter);
            } catch (Exception e) {
                throw new RuntimeException("setPointList的参数需要 yyyy-MM-dd 格式的日期");
            }
            mPointList.add(localDate);
        }
        iCalendar.notifyCalendar();
    }

    public void addPointList(List<String> list) {
        for (String s : list) {
            LocalDate localDate;
            try {
                localDate = LocalDate.parse(s, mDateFormatter);
            } catch (Exception e) {
                throw new RuntimeException("setPointList的参数需要 yyyy-MM-dd 格式的日期");
            }
            if (!mPointList.contains(localDate)) {
                mPointList.add(localDate);
            }
        }
        iCalendar.notifyCalendar();
    }

    // 设置替换农历的文字
    public void setReplaceLunarStrMap(Map<String, String> replaceLunarStrMap) {
        mReplaceLunarStrMap.clear();
        Set<String> keys = replaceLunarStrMap.keySet();
        for (String key : keys) {
            LocalDate localDate;
            try {
                localDate = LocalDate.parse(key, mDateFormatter);
            } catch (Exception e) {
                throw new RuntimeException("setReplaceLunarStrMap的参数需要 yyyy-MM-dd 格式的日期");
            }
            mReplaceLunarStrMap.put(localDate, replaceLunarStrMap.get(key));
        }
        iCalendar.notifyCalendar();
    }

    // 设置替换农历的颜色
    public void setReplaceLunarColorMap(Map<String, Integer> replaceLunarColorMap) {
        mReplaceLunarColorMap.clear();
        Set<String> keys = replaceLunarColorMap.keySet();
        for (String key : keys) {
            LocalDate localDate;
            try {
                localDate = LocalDate.parse(key, mDateFormatter);
            } catch (Exception e) {
                throw new RuntimeException("setReplaceLunarColorMap的参数需要 yyyy-MM-dd 格式的日期");
            }
            mReplaceLunarColorMap.put(localDate, replaceLunarColorMap.get(key));
        }
        iCalendar.notifyCalendar();
    }


    private Rect getDrawableBounds(int centerX, int centerY, Drawable drawable) {
        if (drawable == null) {
            return new Rect();
        }
        return new Rect(
                centerX - drawable.getIntrinsicWidth() / 2,
                centerY - drawable.getIntrinsicHeight() / 2,
                centerX + drawable.getIntrinsicWidth() / 2,
                centerY + drawable.getIntrinsicHeight() / 2
        );
    }

    private int[] getToadyLocation(float centerX, float centerY) {
        int[] location = new int[2];
        location[0] = (int) (centerX - NAttrs.INSTANCE.getPointDistance());
        location[1] = (int) (centerY - NAttrs.INSTANCE.getPointDistance());

        return location;
    }


    private void drawSex(LocalDate localDate, Canvas canvas, RectF rectF) {
        NoteUtils.DayNote dayNote = NoteUtils.getDayNote(localDate);
        if (dayNote.haveSex == 1) {
            //绘制
            Drawable drawable = ContextCompat.getDrawable(mContext, R.mipmap.icon_sex);
            Rect drawableBounds = getDrawableBounds((int) (rectF.centerX() + NAttrs.INSTANCE.getPointDistance()), (int) (rectF.centerY() - NAttrs.INSTANCE.getPointDistance()), drawable);
            drawable.setBounds(drawableBounds);
            //drawable.setAlpha(alphaColor);
            drawable.draw(canvas);
        }
    }

    private void drawJing(LocalDate localDate, Canvas canvas, RectF rectF) {
        if (jingData.contains(localDate)) {
            Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.bg_jing);
            Rect drawableBounds = getDrawableBounds((int) (rectF.centerX()), (int) (rectF.centerY()), drawable);
            drawable.setBounds(drawableBounds);
            //drawable.setAlpha(alphaColor);
            drawable.draw(canvas);
        }
    }

    private void drawYuchan(LocalDate localDate, Canvas canvas, RectF rectF) {
        Drawable drawable = ContextCompat.getDrawable(mContext, R.mipmap.ic_gravidanza);
        int iconSize = dpToPx(12);
        drawable.setBounds(0, 0, iconSize, iconSize);

        Rect drawableBounds = new Rect(
                (int) rectF.centerX() - iconSize / 2,
                (int) rectF.centerY() - iconSize / 2 - (int) NAttrs.INSTANCE.getPointDistance(),
                (int) rectF.centerX() + iconSize / 2,
                (int) rectF.centerY() + iconSize / 2 - (int) NAttrs.INSTANCE.getPointDistance()
        );
        drawable.setBounds(drawableBounds);

        drawable.draw(canvas);


    }

    private void drawPaiLuan(LocalDate localDate, Canvas canvas, RectF rectF) {
        if (paiLuanRi.contains(localDate)) {
            Drawable drawable = ContextCompat.getDrawable(mContext, R.mipmap.ic_luan);
            Rect drawableBounds = getDrawableBounds((int) (rectF.centerX() + NAttrs.INSTANCE.getPointDistance()), (int) (rectF.centerY() - NAttrs.INSTANCE.getPointDistance()), drawable);
            drawable.setBounds(drawableBounds);
            drawable.draw(canvas);
        }
    }

    private void drawShiJiJing(LocalDate localDate, Canvas canvas, RectF rectF) {
        if (jingShiJiData.contains(localDate)) {
            Drawable drawable = ContextCompat.getDrawable(mContext, R.mipmap.ic_shijijing);
            Rect drawableBounds = getDrawableBounds((int) (rectF.centerX() + NAttrs.INSTANCE.getPointDistance()), (int) (rectF.centerY() - NAttrs.INSTANCE.getPointDistance()), drawable);
            drawable.setBounds(drawableBounds);
            drawable.draw(canvas);
        }
    }


    private void drawYiYunQi(LocalDate localDate, Canvas canvas, RectF rectF) {
        if (yiYunQi.contains(localDate)) {
            Drawable drawable = ContextCompat.getDrawable(mContext, R.drawable.bg_yiyun);
            Rect drawableBounds = getDrawableBounds((int) rectF.centerX(), (int) rectF.centerY(), drawable);
            drawable.setBounds(drawableBounds);
            //drawable.setAlpha(alphaColor);
            drawable.draw(canvas);
            mTextPaint.setTextSize(NAttrs.INSTANCE.getLunarTextSize());
            mTextPaint.setColor(Color.parseColor("#FF557C"));
            canvas.drawText("易孕期", rectF.centerX(), rectF.centerY() + NAttrs.INSTANCE.getLunarDistance(), mTextPaint);
        }
    }


    private void initJingData() {
        this.paiLuanRi = CalendarUtils.getPaiLuanRi();
        this.yiYunQi = CalendarUtils.getYiYunRi(this.paiLuanRi);
        this.jingData = CalendarUtils.getJingData();
        this.yuChanData = CalendarUtils.getYuChanQi();
        this.jingShiJiData = CalendarUtils.getJingShiJiData();
     }

    public void notifyCalendar() {
        initJingData();
        iCalendar.notifyCalendar();
    }

    private int dpToPx(int dp) {
        float density = mContext.getResources().getDisplayMetrics().density;
        return (int) (dp * density + 0.5f);
    }
}
